// 用 timing wheel 踢掉空闲连接。
#ifndef MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H
#define MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H
#include <muduo/net/TcpServer.h>
#include <muduo/base/copyable.h>
#include <boost/circular_buffer.hpp>
#include <boost/unordered_set.hpp>
#include <boost/version.hpp>

#if BOOST_VERSION < 104700
namespace boost {
	template <typename T>
	inline size_t hash_value(const boost::shared_ptr<T>& x) {
		return boost::hash_value(x.get());
	}
}
#endif

// RFC 862
class EchoServer {
public:
	EchoServer(muduo::net::EventLoop *loop, const muduo::net::InetAddress &listenAddr, int idleSeconds);

	void Start();

private:
	void OnConnection(const muduo::net::TcpConnectionPtr &conn);
	void OnMessage(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *buf, muduo::Timestamp time);
	void OnTimer();

	void DumpConnectionBuckets() const;

	typedef boost::weak_ptr<muduo::net::TcpConnection> WeakTcpConnectionPtr;

	struct Entry : public muduo::copyable {
		explicit Entry(const WeakTcpConnectionPtr &weakConn)
			: weakConn_(weakConn) {
		}

		// Entry(const Entry &rhs)
		// 	: weakConn_(rhs.weakConn_){
		// }

		// Entry(Entry &&rhs)
		// 	: weakConn_(rhs.weakConn_){
		// }

		// Entry& operator=(const Entry &rhs) {
		// 	weakConn_ = rhs.weakConn_;
		// 	return *this;
		// }

		// 说明该连接已经超过指定秒数未发送消息，因此关闭。
		~Entry() {
			muduo::net::TcpConnectionPtr conn = weakConn_.lock();
			if (conn)
				conn->shutdown();
		}

		WeakTcpConnectionPtr weakConn_;
	};

	typedef boost::shared_ptr<Entry> EntryPtr;
	typedef boost::weak_ptr<Entry> WeakEntryPtr;
	typedef boost::unordered_set<EntryPtr> Bucket;
	typedef boost::circular_buffer<Bucket> WeakConnectionList;

	muduo::net::TcpServer server_;
	// 每一秒中添加一个空的 Bucket ，
	// 若该连接收到消息则把 EntryPtr 添加到当前 buckets 的末尾的 Bucket 中，
	// 若一直没有消息收到，则 Bucket 被析构，其中所有的 Entry 被析构，然后关闭 TcpConnection 。
	WeakConnectionList connectionBuckets_;
};

#endif // MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H
